package com.bsoft.ecommerce.service.impl;

import com.alibaba.fastjson.JSON;
import com.bsoft.ecommerce.constant.AuthorityConstant;
import com.bsoft.ecommerce.constant.CommonConstant;
import com.bsoft.ecommerce.dao.EcommerceUserDao;
import com.bsoft.ecommerce.entity.EcommerceUser;
import com.bsoft.ecommerce.service.IJWTService;
import com.bsoft.ecommerce.vo.LoginUserInfo;
import com.bsoft.ecommerce.vo.UsernameAndPassword;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sun.misc.BASE64Decoder;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.UUID;

/**
 * @program: e-commerce-springclound
 * @description:
 * @author: hdh
 * @create: 2022:06:21 10:45
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class JWTServiceImpl implements IJWTService {
//
//    private final EcommerceUserDao ecommerceUserDao;
//
//    public JWTServiceImpl(EcommerceUserDao ecommerceUserDao) {
//        this.ecommerceUserDao = ecommerceUserDao;
//    }
//
//    @Override
//    public String generateToken(String username, String password) throws Exception {
//        return generateToken(username, password, 0);
//    }
//
//    @Override
//    public String generateToken(String username, String password, int expire) throws Exception {
//        //验证用户是否能够通过授权验证
//        log.info("用户名"+username+"密码"+password);
//        EcommerceUser byUsernameAndPassword = ecommerceUserDao.findByUsernameAndPassword(username, password);
//        log.info("------------------------------------",null==byUsernameAndPassword);
//        if (null == byUsernameAndPassword) {
//            log.error("can not find user [{}],[{}]", username, password);
//            return null;
//        }
//        //token 中塞入对象 即JWT 中存储的信息 后端拿到信息就可以知道是哪个用户再操作
//        LoginUserInfo loginUserInfo = new LoginUserInfo(byUsernameAndPassword.getId(), byUsernameAndPassword.getPassword());
//        if (expire <= 0) {
//            expire = AuthorityConstant.DEFAULT_EXPIRE_DAY;
//        }
//        //计算超时时间
//        ZonedDateTime zdt = LocalDate.now().plus(expire, ChronoUnit.DAYS).atStartOfDay(ZoneId.systemDefault());
//        Date expiredate = Date.from(zdt.toInstant());
//        return Jwts.builder().claim(CommonConstant.JWT_USER_INFO_KEY, JSON.toJSON(loginUserInfo))
//                //jwt id
//
//                .setId(UUID.randomUUID().toString())
//                //jwt 过期时间
//                .setExpiration(expiredate)
//                // jwt 签名  加密
//                .signWith(getPrivateKey(), SignatureAlgorithm.RS256)
//                .compact();
//    }
//
//    @Override
//    public String registerAndGenerateToken(UsernameAndPassword usernameAndPassword) throws Exception {
//        //先去校验用户名是否存在 如果存在，不能重复注册
//        EcommerceUser byUsername = ecommerceUserDao.findByUsername(usernameAndPassword.getPassword());
//        if (null != byUsername) {
//            log.error("username is reginstered []", byUsername.getUsername());
//            return null;
//        }
//        EcommerceUser ecommerceUser = new EcommerceUser();
//        ecommerceUser.setUsername(usernameAndPassword.getUsername());
//        ecommerceUser.setPassword(usernameAndPassword.getPassword());
//        ecommerceUser.setExtra_info("{}");
//        //注册一个新用户 写一条记录到数据表中
//        ecommerceUser = ecommerceUserDao.save(ecommerceUser);
//        log.info("register user sucesses ", ecommerceUser.getUsername(), ecommerceUser.getId());
//        //生成token 返回
//
//        return generateToken(ecommerceUser.getUsername(), ecommerceUser.getPassword());
//    }
//    //根据本地存储的私钥获取到PrivateKey对象
//
//    private PrivateKey getPrivateKey() throws Exception {
//        PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(new BASE64Decoder().decodeBuffer(AuthorityConstant.PRIVATE_KEY));
//        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//        return keyFactory.generatePrivate(priPKCS8);
//    }
private final EcommerceUserDao ecommerceUserDao;

    public JWTServiceImpl(EcommerceUserDao ecommerceUserDao) {
        this.ecommerceUserDao = ecommerceUserDao;
    }

    @Override
    public String generateToken(String username, String password) throws Exception {
          log.info("测试一下"+generateToken(username, password, 0));
        return generateToken(username, password, 0);
    }

    @Override
    public String generateToken(String username, String password, int expire)
            throws Exception {

        // 首先需要验证用户是否能够通过授权校验, 即输入的用户名和密码能否匹配数据表记录
        EcommerceUser ecommerceUser = ecommerceUserDao.findByUsernameAndPassword(
                username, password
        );
        log.info("用户信息-------------------"+ecommerceUser);
        if (null == ecommerceUser) {
            log.error("can not find user: [{}], [{}]", username, password);
            return null;
        }

        // Token 中塞入对象, 即 JWT 中存储的信息, 后端拿到这些信息就可以知道是哪个用户在操作
        LoginUserInfo loginUserInfo = new LoginUserInfo(
                ecommerceUser.getId(), ecommerceUser.getUsername()
        );

        if (expire <= 0) {
            expire = AuthorityConstant.DEFAULT_EXPIRE_DAY;
        }

        // 计算超时时间
        ZonedDateTime zdt = LocalDate.now().plus(expire, ChronoUnit.DAYS)
                .atStartOfDay(ZoneId.systemDefault());
        Date expireDate = Date.from(zdt.toInstant());
        log.info("进来了----------------------------"+Jwts.builder()
                // jwt payload --> KV
                .claim(CommonConstant.JWT_USER_INFO_KEY, JSON.toJSONString(loginUserInfo))
                // jwt id
                .setId(UUID.randomUUID().toString())
                // jwt 过期时间
                .setExpiration(expireDate)
                // jwt 签名 --> 加密
                .signWith(getPrivateKey(), SignatureAlgorithm.RS256)
                .compact());
        String ss= Jwts.builder()
                // jwt payload --> KV
                .claim(CommonConstant.JWT_USER_INFO_KEY, JSON.toJSONString(loginUserInfo))
                // jwt id
                .setId(UUID.randomUUID().toString())
                // jwt 过期时间
                .setExpiration(expireDate)
                // jwt 签名 --> 加密
                .signWith(getPrivateKey(), SignatureAlgorithm.RS256)
                .compact();
        return   ss;
    }

    @Override
    public String registerUserAndGenerateToken(UsernameAndPassword usernameAndPassword)
            throws Exception {

        // 先去校验用户名是否存在, 如果存在, 不能重复注册
        EcommerceUser oldUser = ecommerceUserDao.findByUsername(
                usernameAndPassword.getUsername());
        if (null != oldUser) {
            log.error("username is registered: [{}]", oldUser.getUsername());
            return null;
        }

        EcommerceUser ecommerceUser = new EcommerceUser();
        ecommerceUser.setUsername(usernameAndPassword.getUsername());
        ecommerceUser.setPassword(usernameAndPassword.getPassword());   // MD5 编码以后
        ecommerceUser.setExtra_info("{}");

        // 注册一个新用户, 写一条记录到数据表中
        ecommerceUser = ecommerceUserDao.save(ecommerceUser);
        log.info("register user success: [{}], [{}]", ecommerceUser.getUsername(),
                ecommerceUser.getId());

        // 生成 token 并返回
        return generateToken(ecommerceUser.getUsername(), ecommerceUser.getPassword());
    }

    /**
     * <h2>根据本地存储的私钥获取到 PrivateKey 对象</h2>
     * */
    private PrivateKey getPrivateKey() throws Exception {

        PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
                new BASE64Decoder().decodeBuffer(AuthorityConstant.PRIVATE_KEY));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(priPKCS8);
    }

}
